#pragma once

#include <vector>
#include <sys/epoll.h>
#include <mutex>
#include <functional>

using runnable = std::function<void()>;

class EventLoop final 
{
public:
    EventLoop();
    ~EventLoop();

    static EventLoop *current_eventloop();

    void loop();

    void timeout(int interval, const runnable& slot);
    void singleshot(int interval, const runnable& slot, bool one_shot);

    void quit();

private:
    int epoll_open() const;
    void wakeup() const;

    int create_event_fd() const;
    int create_timer_fd() const;

    bool add_read_watch(int fd);

    void handle_timeout(const struct epoll_event& e);
    void handle_wakeup(const struct epoll_event& e);

private:
    // bool looping = false;

    bool m_exited = false;

    const int m_epoll_fd;

    std::vector<epoll_event> m_events;

    std::mutex m_mtx;

    int m_wakeup_fd;    //for quit
    int m_timeout_fd;   //for timeout

    runnable m_timeout_slot;

};